import { Context, Next } from 'koa'
import { z } from 'zod'

export interface ApiError extends Error {
    status?: number
    code?: string
}

export class CustomError extends Error implements ApiError {
    public status: number
    public code: string

    constructor(message: string, status: number = 500, code: string = 'INTERNAL_ERROR') {
        super(message)
        this.name = 'CustomError'
        this.status = status
        this.code = code
    }
}

export const errorHandler = async (ctx: Context, next: Next) => {
    try {
        await next()
    } catch (error: any) {
        const err = error as ApiError

        // Zod 验证错误
        if (error instanceof z.ZodError) {
            ctx.status = 400
            ctx.body = {
                success: false,
                message: 'Validation failed',
                code: 'VALIDATION_ERROR',
                errors: error.errors.map(e => ({
                    path: e.path.join('.'),
                    message: e.message
                }))
            }
            return
        }

        // 自定义错误
        if (error instanceof CustomError) {
            ctx.status = error.status
            ctx.body = {
                success: false,
                message: error.message,
                code: error.code
            }
            return
        }

        // Prisma 错误
        if (error.code?.startsWith('P')) {
            ctx.status = 400
            ctx.body = {
                success: false,
                message: 'Database operation failed',
                code: 'DATABASE_ERROR'
            }
            return
        }

        // JWT 错误
        if (error.name === 'JsonWebTokenError') {
            ctx.status = 401
            ctx.body = {
                success: false,
                message: 'Invalid token',
                code: 'INVALID_TOKEN'
            }
            return
        }

        if (error.name === 'TokenExpiredError') {
            ctx.status = 401
            ctx.body = {
                success: false,
                message: 'Token expired',
                code: 'TOKEN_EXPIRED'
            }
            return
        }

        // 默认错误处理
        ctx.status = err.status || 500
        ctx.body = {
            success: false,
            message: err.message || 'Internal server error',
            code: err.code || 'INTERNAL_ERROR'
        }

        // 记录错误日志
        ctx.log?.error(error, 'Unhandled error occurred')
    }
}

// 常用错误创建函数
export const createError = {
    badRequest: (message: string = 'Bad request') => new CustomError(message, 400, 'BAD_REQUEST'),
    unauthorized: (message: string = 'Unauthorized') => new CustomError(message, 401, 'UNAUTHORIZED'),
    forbidden: (message: string = 'Forbidden') => new CustomError(message, 403, 'FORBIDDEN'),
    notFound: (message: string = 'Not found') => new CustomError(message, 404, 'NOT_FOUND'),
    conflict: (message: string = 'Conflict') => new CustomError(message, 409, 'CONFLICT'),
    internal: (message: string = 'Internal server error') => new CustomError(message, 500, 'INTERNAL_ERROR')
}
